package com.mbengue.corp.artisan.utils.abstrait;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public abstract class PdfExporteur implements Serializable {
  private static final long serialVersionUID = -2594835147033386163L;
  private final Document document;
  private final PdfWriter ecrivain;
  private final ColumnText colonne;
  private final int nbLigne;
  private int marge;

  public PdfExporteur(String nomFichier, int nbLigne, boolean portraitOuPaysage) throws DocumentException, IOException {
    Rectangle orientation;
    if (portraitOuPaysage) {
      orientation = PageSize.A4;
      this.marge = 495;
    } else {
      orientation = PageSize.A4.rotate();
      this.marge = 743;
    }
    this.document = new Document(orientation, 50, 50, 75, 75);
    this.ecrivain = PdfWriter.getInstance(this.document, new FileOutputStream(nomFichier));
    this.document.open();
    this.document.addCreationDate();
    this.colonne = new ColumnText(ecrivain.getDirectContent());
    this.nbLigne = nbLigne;
  }

  @SuppressWarnings("unused")
  private PdfPTable creerTable(Object[][] donnees, String[] enTete, float[] largeurColonnes) {
    if (enTete == null) {
      return null;
    }

    PdfPTable tableau = new PdfPTable(largeurColonnes);
    tableau.setWidthPercentage(100);
    tableau.setSpacingBefore(15);
    tableau.getDefaultCell().setUseAscender(true);
    tableau.getDefaultCell().setUseDescender(true);
    tableau.getDefaultCell().setBackgroundColor(BaseColor.LIGHT_GRAY);
    for (String element : enTete) {
      tableau.addCell(element);
    }

    tableau.getDefaultCell().setBackgroundColor(null);
    tableau.getDefaultCell().setMinimumHeight(15f);
    for (Object[] donnee : donnees) {
      for (Object element : donnee) {
        if (element instanceof Double) {
          tableau.addCell(Double.toString((Double) element));
        } else if (element instanceof Timestamp) {
          String date = new SimpleDateFormat("dd-MM-yyyy").format((Timestamp) element);
          tableau.addCell(date);
        } else {
          tableau.addCell((String) element);
        }
      }
    }

    for (int i = donnees.length; i < this.nbLigne; i++) {
      for (String element : enTete) {
        tableau.addCell("");
      }
    }
    tableau.completeRow();

    return tableau;
  }

  public void creerPdf(Object[][] donnees, String[] enTete, float[] largeurColonnes) throws DocumentException {
    // Definition de la colonne
    float[][] x = { { this.document.left(), this.document.left() + this.marge },
        { this.document.right() - this.marge, this.document.right() } };
    this.colonne.addElement(this.creerTable(donnees, enTete, largeurColonnes));
    int count = 0;
    float height = 0;
    int status = ColumnText.START_COLUMN;

    while (ColumnText.hasMoreText(status)) {
      // ajoute une en-tête à toute les nouvelles pages
      if (count == 0) {
        height = this.ajouterEnteteDocument(this.ecrivain.getPageNumber());
      }
      // met à jour les dimensions de la colonne courante
      this.colonne.setSimpleColumn(x[count][0], this.document.bottom(), x[count][1], this.document.top() - height - 10);
      // passe au contenu suivant;
      status = this.colonne.go();
      // cree une nouvelle page si on arrive à la fin de la colonne
      if (++count > 1) {
        count = 0;
        this.document.newPage();
      }
      this.ajouterFooterDocument(this.ecrivain.getPageNumber());
    }
    this.document.close();
  }

  protected abstract float ajouterEnteteDocument(int page) throws DocumentException;

  protected abstract void ajouterFooterDocument(int page) throws DocumentException;

  public PdfWriter getEcrivain() {
    return ecrivain;
  }

  public Document getDocument() {
    return document;
  }

  public ColumnText getColonne() {
    return colonne;
  }
}
